# Contributor: Frank Oltmanns <alpine@oltmanns.dev>
# Maintainer: Frank Oltmanns <alpine@oltmanns.dev>

pkgname=anki
pkgver=2.1.49
pkgrel=0
# Remember to update the following lines when updating the pkgver
_core_i18n_commit="56d46d658a8badb9f13f48d89ee074419b181f69"
_qtftl_i18n_commit="5359f84328c1484c5db69edbb6b851acc4160095"

# For translations
_core_i18n_repo="anki-core-i18n"
_qtftl_i18n_repo="anki-desktop-ftl"
# The following changes are required to make this version work
# with Alpine/musl.
#
# The patches listed here are necessary to make bazel compilation
# possible on musl. Without the patches the glibc versions of tools
# would be downloaded.
#   - node_repositories
#   - protoc_repository
#   - rust_output
#
# Reasoning for manually building the rust bridge
# -----------------------------------------------
# I spent three days trying to figure out how use Anki's bazel
# environment in a musl context for building it's rust components.
# I got quite far. But getting the rust compiler to use the local
# "protoc" executable is where I ran out of ideas.
#
# That state is preserved here:
# https://gitlab.alpinelinux.org/fraolt/aports/-/tree/anki_2.1.49_savepoint/testing/anki
#
# I'm not spending any more time on bending bazel to my will.
#
# Now, I'm going a similar route as the fine people at FreeBSD and build
# the rust components without bazel. Instead, bazel will just pick up
# build results.

pkgdesc="flashcard program using spaced repetition"
url="https://apps.ankiweb.net/"
# armhf blocked by qt5-qtdeclarative -> py3-qtwebengine
# ppc64le and s390x are blocked by py3-qtwebengine
# riscv64 blocked by qt5-qtwebengine -> py3-qtwebengine
# x86, armv7 blocked by bazel4
arch="x86_64 aarch64"
license="AGPL-3.0-or-later"
options="!check" # no test suite provided
# The makedepends and depends are copied from the PKGBUILD
# for 2.1.49 in the Arch User Repository
makedepends="
	rsync
	python3
	python3-dev
	protoc
	bazel4
	maturin
	rust
	cargo
	py3-installer
	pythonispython3
	npm
	nodejs
	yarn
	openssl-dev
	"
depends="
	py3-beautifulsoup4
	py3-requests
	py3-wheel

	py3-pysocks
	py3-decorator
	py3-protobuf
	py3-distro
	py3-stringcase

	py3-send2trash
	py3-markdown
	py3-jsonschema
	py3-pyaudio
	py3-qtwebengine
	py3-flask
	py3-flask-cors
	py3-waitress
	py3-qt5
	"
source="
	https://github.com/ankitects/anki/archive/$pkgver/anki-$pkgver.tar.gz
	$pkgname-$pkgver-ftlrslib.tar.gz::https://github.com/ankitects/$_core_i18n_repo/archive/$_core_i18n_commit.tar.gz
	$pkgname-$pkgver-ftlextra.tar.gz::https://github.com/ankitects/$_qtftl_i18n_repo/archive/$_qtftl_i18n_commit.tar.gz
	node_repositories.patch
	no_orjson.patch
	protoc_repository.patch
	rust_output.patch
	pylib_musllinux.patch
	scripts_status.patch
	local_ftl_repos.patch
	waitress_asyncore_use_poll.patch
	BUILD.bazel-pylib-rsbridge
	BUILD.bazel-rslib-i18n
	BUILD.bazel-rust_output-strings_json
	BUILD.bazel-rust_output-librsbridge
	BUILD.bazel-i18n
	"

prepare() {
	default_prepare

	# The .bazelversion file limits us to the use of exactly bazel 4.0.0.
	# Let's use the version that comes with alpine instead. :-)
	rm "$builddir"/.bazelversion

	# Create a local node repository as per https://github.com/ankitects/anki/blob/2.1.49/docs/new-platform.md#nodejs
	mkdir -p "$builddir"/local_node/node/bin
	mkdir -p "$builddir"/local_node/node/lib
	touch "$builddir"/local_node/WORKSPACE
	[ -e "$builddir"/local_node/node/bin/node ] || ln -s /usr/bin/node "$builddir"/local_node/node/bin/node
	[ -e "$builddir"/local_node/node/lib/node_modules ] || ln -s /usr/lib/node_modules "$builddir"/local_node/node/lib/node_modules

	# Create a local protoc repository in a similar way (inspired by FreeBSD anki patches)
	mkdir -p "$builddir"/local_protoc/bin
	touch "$builddir"/local_protoc/WORKSPACE
	[ -e "$builddir"/local_protoc/bin/protoc ] || ln -s /usr/bin/protoc local_protoc/bin/protoc

	# Create a directory for the rust output
	mkdir -p "$builddir"/rust_output/strings_json
	mkdir -p "$builddir"/rust_output/librsbridge
	touch "$builddir"/rust_output/WORKSPACE
	cp "$srcdir"/BUILD.bazel-rust_output-strings_json "$builddir"/rust_output/strings_json/BUILD.bazel
	cp "$srcdir"/BUILD.bazel-rust_output-librsbridge "$builddir"/rust_output/librsbridge/BUILD.bazel

	# Overwrite the BUILD.bazel files, so that they just copy files from
	# rust_output instead of actually building the rust components via
	# bazel build.
	cp "$srcdir"/BUILD.bazel-pylib-rsbridge "$builddir"/pylib/rsbridge/BUILD.bazel
	cp "$srcdir"/BUILD.bazel-rslib-i18n "$builddir"/rslib/i18n/BUILD.bazel

	# Links to translations
	[ -e "$builddir"/ftlrslib ] || ln -s "$srcdir"/"$_core_i18n_repo-$_core_i18n_commit" "$builddir"/ftlrslib
	[ -e "$builddir"/ftlextra ] || ln -s "$srcdir"/"$_qtftl_i18n_repo-$_qtftl_i18n_commit" "$builddir"/ftlextra
	cp "$srcdir"/BUILD.bazel-i18n "$builddir"/ftlrslib/BUILD.bazel
	cp "$srcdir"/BUILD.bazel-i18n "$builddir"/ftlextra/BUILD.bazel

	# Use local PyQt5 install as per fourth bullet of  https://github.com/ankitects/anki/blob/2.1.49/docs/new-platform.md#protobuf--python
	echo "build --action_env=PYTHON_SITE_PACKAGES=$(python3 -c 'import site; print(site.getsitepackages()[0])')" >> "$builddir"/user.bazelrc

	# Create buildinfo, this is apparently used at runtime to check
	# that the rust and python build come from the same source.
	BUILDHASH=$(git ls-remote https://github.com/ankitects/anki.git refs/tags/$pkgver^{} | cut -c -8)
	echo "STABLE_VERSION $pkgver" > "$builddir"/rust_output/buildinfo.txt
	echo "STABLE_BUILDHASH $BUILDHASH" >> "$builddir"/rust_output/buildinfo.txt

	# Also fix the script for the python buildinfo
	sed -i -e s/PKGVER/$pkgver/ "$builddir"/scripts/status.sh
}

# Overview of the build process
#
# Steps 1 and 2 are built separately from the bazel build process.
#
# 1. rslib (Rust library, implictly built by step 2)
#    -> produces rust_output/strings_json/strings.json
# 2. pylib/rsbridge (Rust/Python bridge)
#    -> produces rust_output/librsbridge/librsbridge.so
# 3. The remaining components (Python, Qt5 and JS) are built by bazel
build() {
	# Step 1 and 2 from above
	# BAZEL=1 is required otherwise rslib/build/main.rs produces a dummy
	# buildinfo.txt that doesn't contain the actual build hash.
	BAZEL=1 \
		BUILDINFO="$builddir"/rust_output/buildinfo.txt \
		PROTO_TOP="$builddir"/proto/.top_level \
		BACKEND_PROTO="$builddir"/rslib/backend.proto \
		RSLIB_FTL_ROOT="$builddir"/ftlrslib/l10n.toml \
		EXTRA_FTL_ROOT="$builddir"/ftlextra/l10n.toml \
		/usr/bin/cargo build --manifest-path ./pylib/rsbridge/Cargo.toml --verbose --release
	# These files are required for the remaining build process via bazel so
	# copy them to the local repository.
	cp ./target/release/librsbridge.so ./rust_output/librsbridge/
	find ./target -name strings.json -exec cp \{\} ./rust_output/strings_json \;

	# Step 3 from above
	# Limit bazel jobs to 1 due random build failures while compiling TS files
	# via "tsc".
	bazel --output_user_root="$builddir"/bazel-build/ build --verbose_failures --jobs 1 --subcommands --sandbox_debug -c opt dist
}

package() {
	python3 -m installer --destdir "$pkgdir" bazel-bin/pylib/anki/anki-*.whl
	python3 -m installer --destdir "$pkgdir" bazel-bin/qt/aqt/aqt-*.whl

	install -Dm755 qt/runanki.py "$pkgdir"/usr/bin/anki
	install -Dm644 qt/linux/anki.desktop "$pkgdir"/usr/share/applications/anki.desktop
	install -Dm644 qt/linux/anki.png "$pkgdir"/usr/share/pixmaps/anki.png
}
sha512sums="
bde874a9ae39873e5c0b1dad1815e6cfb898cd0f788a684768c53fd847dbb92fa5c293a0fae8b527e70d380510cd3fc465806053d3e555281885accea3fcc2b0  anki-2.1.49.tar.gz
f9d521080ecc9679d3e1dff7773785383efe468da9517eef206d483b3f49e4abf4cb4649368b732d9ed255f1971817685f1988d8b13f539d2a3e58fb4c8a09fc  anki-2.1.49-ftlrslib.tar.gz
269d7cae19404d788f6bd1335e0a55ef3f1d41d0089a62e62ecfa2fae2afe0ebbac519c69eabfa47209c9841ab675d94e434ae05e0469e47d87d01c094998dac  anki-2.1.49-ftlextra.tar.gz
1ef2b13aebaee3889d7262ce7decb212554bb8634138f970e8ab89a834e481665555ac62a051ad1252b140651278572486def0aa850c35f8377084726db58c5d  node_repositories.patch
35f25ec02d01016eb759490ff1fae016c979d867f35fd2bf7d322a74afc0a19fa131b1d34e93b2ddb7182e7e388b6892bf42921bcb249b6e55b0323007b200fe  no_orjson.patch
b15e4a3f3f88620fb701aec972600b8f11cc4d410c6047e5a588c4ddf4e4795704439d9473b18022eeb3da0fbb2aa91c73300527da6654f2a31aa6f39f292562  protoc_repository.patch
aeaad302c8c9c96cba24335d2fee5712c5d1c4335e70a0adb9db3399eaf961af849681884076f1c8a28be853500bec71a1c331ea0148be9b1d27ebc25905fff5  rust_output.patch
cf0f340d142b216e55ea56875e7b8321efdbd14dae0f0ab22df1fc6acdb8291ad657aa158a216d8505e8de392a2d33dd1871f9809f0619d86d545877a3e208cc  pylib_musllinux.patch
4d9212acd136ec61d9f33888b772b150130201df4a83e60ebf8be7a68741322f11c75d3b007568e4fb0b898ec8918f546821b1b6939d0a96c69711bdd9e6ae36  scripts_status.patch
e930280a29d8951746168782cffb6eb07b1d91307e7f9f638ce55e1c0d246ae27799282850e88c21f733ff244e8b9d4ef82023bf8bc882b8e178d380d018dd42  local_ftl_repos.patch
28fc9848715407d4b172935f071bd344c2fa4c2145501eb39c121030335f1dd517165bcb9550e8c88a0748c8f9d9e4c02c77b02aa22e05642f0358e45d18a4c4  waitress_asyncore_use_poll.patch
5fa979393b7c2b1794275a17c6a3c1b092d25545c1473e96199d8732fc442e5161da34354e7a6fadf36d2d605a565f464aa5ae759da25c1f288bda0c362e36e3  BUILD.bazel-pylib-rsbridge
19956d70ece7fc735e31c10c6f3466db8c713c9999ff3a38de323d0dce723ad512bb5ffb4d1428aa6268b436e4a4cfd604de1567f1b2948620d494a6993a7280  BUILD.bazel-rslib-i18n
f98d1b8c33fd186db68da2f978ce4cb409e288c999d17355cf15992501cd640eece3f367068fac8e1936a4b2b4d83e87e5462890a7aaee4316a5572f4989f930  BUILD.bazel-rust_output-strings_json
1948c4c77587d057ff358a625715ea90de109aed60b6e8e66f277235650ba5cbfc5756d066ca483631036afe2105cc6f8e7bad717504cbcf449d1103028b55c6  BUILD.bazel-rust_output-librsbridge
360da5e8cd3f4cbacabf3ec5233f8c958b012193c9897097c6b0b5d8b898d18c2f82cfe5391f52f275e1b3721bd5572d7b3cb0901308618eade3edd31389ff16  BUILD.bazel-i18n
"
